package com.ticket.system.service.impl;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

import cn.hutool.core.util.RandomUtil;
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
import com.ticket.common.constant.CacheConstants;
import com.ticket.common.constant.PerformConstants;
import com.ticket.common.core.domain.entity.SysUser;
import com.ticket.common.core.domain.model.LoginUser;
import com.ticket.common.core.redis.RedisCache;
import com.ticket.common.exception.ServiceException;
import com.ticket.common.utils.DateUtils;
import com.ticket.common.utils.SecurityUtils;
import com.ticket.common.utils.StringUtils;
import com.ticket.common.utils.ip.IpUtils;
import com.ticket.system.domain.*;
import com.ticket.system.domain.vo.RechargeVo;
import com.ticket.system.mapper.SysUserMapper;
import com.ticket.system.mapper.YanchuConsumeRecordMapper;
import com.ticket.system.mapper.YanchuRechargeRulesMapper;
import com.ticket.system.service.ITYanchuPointsRuleService;
import com.ticket.system.service.IYanchuOrderService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ticket.system.mapper.YanchuStorageCradMapper;
import com.ticket.system.service.IYanchuStorageCradService;
import org.springframework.transaction.annotation.Transactional;

/**
 * 储存卡信息（包含绑定信息）Service业务层处理
 * 
 * @author ruoyi
 * @date 2023-12-12
 */
@Service
public class YanchuStorageCradServiceImpl implements IYanchuStorageCradService 
{
    private static final Logger logger = LoggerFactory.getLogger(YanchuStorageCradServiceImpl.class);
    @Autowired
    private YanchuStorageCradMapper yanchuStorageCradMapper;

    @Autowired
    private YanchuConsumeRecordMapper yanchuConsumeRecordMapper;

    @Autowired
    private YanchuRechargeRulesMapper yanchuRechargeRulesMapper;
    @Autowired
    private RedisCache redisCache;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private IYanchuOrderService iYanchuOrderService;

    @Autowired
    private ITYanchuPointsRuleService yanchuPointsRuleService;

    /**
     * 查询储存卡信息（包含绑定信息）
     * 
     * @param id 储存卡信息（包含绑定信息）主键
     * @return 储存卡信息（包含绑定信息）
     */
    @Override
    public YanchuStorageCrad selectYanchuStorageCradById(Long id)
    {
        return yanchuStorageCradMapper.selectYanchuStorageCradById(id);
    }

    /**
     * 查询储存卡信息（包含绑定信息）列表
     * 
     * @param yanchuStorageCrad 储存卡信息（包含绑定信息）
     * @return 储存卡信息（包含绑定信息）
     */
    @Override
    public List<YanchuStorageCrad> selectYanchuStorageCradList(YanchuStorageCrad yanchuStorageCrad)
    {
        return yanchuStorageCradMapper.selectYanchuStorageCradList(yanchuStorageCrad);
    }

    /**
     * 新增储存卡信息（包含绑定信息）
     * 
     * @param yanchuStorageCrad 储存卡信息（包含绑定信息）
     * @return 结果
     */
    @Override
    public int insertYanchuStorageCrad(YanchuStorageCrad yanchuStorageCrad)
    {
        return yanchuStorageCradMapper.insertYanchuStorageCrad(yanchuStorageCrad);
    }

    /**
     * 修改储存卡信息（包含绑定信息）
     * 
     * @param yanchuStorageCrad 储存卡信息（包含绑定信息）
     * @return 结果
     */
    @Override
    public int updateYanchuStorageCrad(YanchuStorageCrad yanchuStorageCrad)
    {
        return yanchuStorageCradMapper.updateYanchuStorageCrad(yanchuStorageCrad);
    }

    /**
     * 批量删除储存卡信息（包含绑定信息）
     * 
     * @param ids 需要删除的储存卡信息（包含绑定信息）主键
     * @return 结果
     */
    @Override
    public int deleteYanchuStorageCradByIds(Long[] ids)
    {
        return yanchuStorageCradMapper.deleteYanchuStorageCradByIds(ids);
    }

    /**
     * 添加消费记录
     *
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int consume(YanchuOrder yanchuOrder)
    {
        int count = yanchuStorageCradMapper.consume(yanchuOrder.getUserId(), yanchuOrder.getBalanceAmt());
        if(count > 0){
            YanchuStorageCrad storageCrad = yanchuStorageCradMapper.selectStorageCradByUserId(yanchuOrder.getUserId());
            if(null == storageCrad){
                throw new ServiceException("添加消费记录失败");
            }
            YanchuConsumeRecord yanchuConsumeRecord = new YanchuConsumeRecord();
            yanchuConsumeRecord.setAmount(yanchuOrder.getBalanceAmt().negate());
            yanchuConsumeRecord.setOrderId(yanchuOrder.getId());
            yanchuConsumeRecord.setConType(PerformConstants.CONSUME_TYPE_BALANCE);
            yanchuConsumeRecord.setCardType(PerformConstants.CARD_TYPE_BALANCE);
            yanchuConsumeRecord.setBalance(storageCrad.getBalance());
            yanchuConsumeRecord.setOperaId(yanchuOrder.getOperaId());
            yanchuConsumeRecord.setStatus(PerformConstants.CARD_STATUS_SUCCESS);
            yanchuConsumeRecord.setBindId(yanchuOrder.getUserId());
            yanchuConsumeRecord.setCreatTime(new Date());
            yanchuConsumeRecord.setOperaId(yanchuOrder.getOperaId());
            yanchuConsumeRecord.setIsDel(0);
            yanchuConsumeRecordMapper.insertYanchuConsumeRecord(yanchuConsumeRecord);
        }

        return count;
    }
    /**
     * 充值
     *
     * @return 结果
     */
    @Override
    public RechargeVo recharge(Long ruleId, BigDecimal amount) throws Exception{
        RechargeVo rechargeVo = new RechargeVo();
        BigDecimal rechargeAmount = amount;
        if(null != ruleId){
            YanchuRechargeRules rule = yanchuRechargeRulesMapper.selectYanchuRechargeRulesById(ruleId);
            if(null == rule){
                throw new ServiceException("规则编码不正确！");
            }

            if(rechargeAmount.compareTo(rule.getRecAmount())>=0){
                rechargeAmount = rechargeAmount.add(rule.getPreAmount());
            }
            rechargeVo.setRuleId(ruleId);
            rechargeVo.setCredits(rule.getPreAmount());
        }
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if(StringUtils.isEmpty(loginUser.getUser().getOpenId())){
            SysUser sysUser = sysUserMapper.selectUserById(loginUser.getUser().getUserId());
            if(null != sysUser && StringUtils.isNotEmpty(sysUser.getOpenId())){
                loginUser.getUser().setOpenId(sysUser.getOpenId());
            }
        }
        logger.info("recharge userId:{} ruleId:{} amount:{}",loginUser.getUser().getUserId(),ruleId,amount);
        YanchuStorageCrad card = yanchuStorageCradMapper.selectStorageCradByUserId(loginUser.getUser().getUserId());
        if(null == card){
            card = new YanchuStorageCrad();
            card.setBalance(BigDecimal.ZERO);
            card.setBindId(loginUser.getUser().getUserId());
            card.setBindTime(new Date());
            int count = yanchuStorageCradMapper.insertYanchuStorageCrad(card);
            if(count <= 0){
                throw new ServiceException("新增储值卡记录失败！");
            }
        }
        rechargeVo.setAmount(amount);
        rechargeVo.setRechargeAmount(rechargeAmount);
        rechargeVo.setUserId(loginUser.getUser().getUserId());//
        rechargeVo.setOrderNo(DateUtils.dateTimeNow()+loginUser.getUser().getUserId()+ RandomUtil.randomInt(1, 1000));
        String key = CacheConstants.RECHARGE_KEY+rechargeVo.getOrderNo();
        logger.info("recharge orderNo:{}",rechargeVo.getOrderNo());
        YanchuOrder yanchuOrder = new YanchuOrder();
        yanchuOrder.setTotalMoney(amount);
        yanchuOrder.setWechatAmt(amount);
        yanchuOrder.setOpenId(loginUser.getUser().getOpenId());
        yanchuOrder.setOrderId(rechargeVo.getOrderNo());
        String ip = IpUtils.getIpAddr();
        yanchuOrder.setUserIp(ip);

        WxPayMpOrderResult response = iYanchuOrderService.unifiedOrder(yanchuOrder,loginUser,"/system/crad/rechargeNotify/forAllUser","充值");
        redisCache.setCacheObject(key,rechargeVo,60, TimeUnit.MINUTES);
        rechargeVo.setResponse(response);
        return rechargeVo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void notifyRecharge(String outTradeNo, BigDecimal totalFee, String transactionId) {
        logger.info("notifyRecharge outTradeNo:{} totalFee:{} transactionId:{}", outTradeNo, totalFee, transactionId);
        String rechargeKey = CacheConstants.RECHARGE_KEY+outTradeNo;
        RechargeVo rechargeVo = redisCache.getCacheObject(rechargeKey);
        if(null == rechargeVo){
            logger.warn("缓存获取充值对象为空:{}",outTradeNo);
            return;
        }
        logger.info("rechargeVo:{}",rechargeVo);
        int count = yanchuStorageCradMapper.recharge(rechargeVo.getUserId(),rechargeVo.getRechargeAmount());
        if(count > 0){
            YanchuStorageCrad storageCrad = yanchuStorageCradMapper.selectStorageCradByUserId(rechargeVo.getUserId());
            if(null == storageCrad){
                throw new ServiceException("获取储值卡信息失败！");
            }
            YanchuConsumeRecord consumeRecord = new YanchuConsumeRecord();
            consumeRecord.setAmount(totalFee);
            consumeRecord.setCardNum(outTradeNo);
            consumeRecord.setConType(PerformConstants.CONSUME_TYPE_RECHARGE);
            consumeRecord.setCardType(PerformConstants.CARD_TYPE_BALANCE);
            consumeRecord.setCreatTime(new Date());
            consumeRecord.setBalance(storageCrad.getBalance());
            consumeRecord.setStatus(PerformConstants.CARD_STATUS_SUCCESS);
            consumeRecord.setOrderNo(rechargeVo.getOrderNo());
            consumeRecord.setBindId(rechargeVo.getUserId());
            consumeRecord.setCredits(rechargeVo.getCredits());
            yanchuConsumeRecordMapper.insertYanchuConsumeRecord(consumeRecord);
            yanchuPointsRuleService.addPoints(5,totalFee,rechargeVo.getUserId());
        }
        redisCache.deleteObject(rechargeKey);
    }

    /**
     * 添加退费记录
     *
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int refund(YanchuOrder yanchuOrder,YanchuRefundOrder refundOrder)
    {
        if(!yanchuOrder.getStatus().equals(PerformConstants.ORDER_PAY) &&
                !yanchuOrder.getStatus().equals(PerformConstants.ORDER_WAIT_PAY) &&
                !yanchuOrder.getStatus().equals(PerformConstants.ORDER_CHECKED)){
            return 0;
        }
        BigDecimal amount = yanchuOrder.getBalanceAmt();
        if(null != refundOrder){
            amount = refundOrder.getBalanceAmt();
        }
        logger.info("refund recharge userId:{} balanceAmount:{} amount:{}",yanchuOrder.getUserId(),yanchuOrder.getBalanceAmt(),amount);
        int count = yanchuStorageCradMapper.recharge(yanchuOrder.getUserId(), amount);
        if(count > 0){
            YanchuStorageCrad yanchuStorageCrad = yanchuStorageCradMapper.selectStorageCradByUserId(yanchuOrder.getUserId());
            if(null == yanchuStorageCrad){
                throw new ServiceException("获取储值卡信息失败");
            }
            YanchuConsumeRecord consumeRecord = new YanchuConsumeRecord();
            consumeRecord.setAmount(amount);
            consumeRecord.setOrderId(yanchuOrder.getId());
            consumeRecord.setConType(PerformConstants.REFUND_TYPE_BALANCE);
            consumeRecord.setCardType(PerformConstants.CARD_TYPE_BALANCE);
            consumeRecord.setBalance(yanchuStorageCrad.getBalance());
            consumeRecord.setStatus(PerformConstants.CARD_STATUS_SUCCESS);
            consumeRecord.setBindId(yanchuOrder.getUserId());
            consumeRecord.setCreatTime(new Date());
            consumeRecord.setOperaId(yanchuOrder.getOperaId());
            consumeRecord.setIsDel(0);
            yanchuConsumeRecordMapper.insertYanchuConsumeRecord(consumeRecord);
        }
        return count;
    }

    /**
     * 删除储存卡信息（包含绑定信息）信息
     * 
     * @param id 储存卡信息（包含绑定信息）主键
     * @return 结果
     */
    @Override
    public int deleteYanchuStorageCradById(Long id)
    {
        return yanchuStorageCradMapper.deleteYanchuStorageCradById(id);
    }
}
